/**
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { computed, defineComponent, Ref, ref, SetupContext, watch } from 'vue';
import { comboListProps, ComboListProps, Option } from './combo-list.props';
import ComboListContainer from './components/list-comtainer.component';
import FButtonEdit from '../../button-edit/src/button-edit.component';

import './combo-list.css';
import { useDataSource } from './composition/use-data-source';

export default defineComponent({
    name: 'FComboList',
    props: comboListProps,
    emits: ['clear', 'update:modelValue', 'change'] as (string[] & ThisType<void>) | undefined,
    setup(props: ComboListProps, context: SetupContext) {
        const comboEditorRef: Ref<any> = ref();
        const disable = ref(props.disabled);
        const enableClear = ref(props.enableClear);
        const enableSearch = ref(props.enableSearch);
        const readonly = ref(props.readonly);
        const { dataSource, displayText, editable, modelValue, getSelectedItemsByDisplayText } = useDataSource(props);

        const isMultiSelect = computed(() => props.multiSelect);

        function tryHidePopupOnSelect() {
            const shouldHidePopupOnSelect = !isMultiSelect.value;
            if (shouldHidePopupOnSelect && comboEditorRef.value) {
                comboEditorRef.value.hidePopup();
            }
        }

        function onSelectionChange(selectedItems: Option[]) {
            displayText.value = selectedItems.map((item: Option) => item[props.textField]).join(props.separator);
            modelValue.value = selectedItems.map((item: Option) => item[props.valueField]).join(props.separator);
            context.emit('update:modelValue', modelValue.value);
            context.emit('change', selectedItems);
            tryHidePopupOnSelect();
        }

        function onClear($event: Event) {
            modelValue.value = '';
            context.emit('update:modelValue', '');
            context.emit('clear');
        }

        function onDisplayTextChange(displayText: string) {
            const selectedItems = getSelectedItemsByDisplayText(displayText);
            onSelectionChange(selectedItems);
        }

        function getDisplayText() {
            return displayText.value;
        }

        context.expose({ getDisplayText });

        watch(
            [() => props.disabled, () => props.editable, () => props.enableClear, () => props.enableSearch, () => props.readonly],
            ([newDisabled, newEditable, newEnableClear, newEnableSearch, newReadonly]) => {
                disable.value = newDisabled;
                editable.value = newEditable;
                enableClear.value = newEnableClear;
                enableSearch.value = newEnableSearch;
                readonly.value = newReadonly;
            }
        );

        return () => {
            return (
                <FButtonEdit
                    ref={comboEditorRef}
                    id={props.id}
                    disable={disable.value}
                    readonly={readonly.value}
                    forcePlaceholder={props.forcePlaceholder}
                    editable={editable.value}
                    buttonContent={props.dropDownIcon}
                    placeholder={props.placeholder}
                    enableClear={enableClear.value}
                    maxLength={props.maxLength}
                    tabIndex={props.tabIndex}
                    enableTitle={props.enableTitle}
                    multiSelect={props.multiSelect}
                    inputType={props.multiSelect ? 'tag' : 'text'}
                    v-model={displayText.value}
                    onClear={onClear}
                    onChange={onDisplayTextChange}>
                    <ComboListContainer
                        idField={props.idField}
                        valueField={props.valueField}
                        textField={props.textField}
                        dataSource={dataSource.value}
                        selectedValues={modelValue.value}
                        multiSelect={props.multiSelect}
                        enableSearch={enableSearch.value}
                        height={props.maxHeight}
                        onSelectionChange={onSelectionChange}></ComboListContainer>
                </FButtonEdit>
            );
        };
    }
});
